#include "../include/TLV.h"

namespace wd{
//无参构造
TLV::TLV()
    :_type(0)//字段的值而非字节数（字节数是固定4字节）
     ,_length(0)
{
    memset(data,0,DATA_MAX_SIZE); 
}
//有参构造
TLV::TLV(int t,int len,const char* msg)
    :_type(htonl(t))
     ,_length(htonl(len))
{
    send_data(msg,len);
}
//将数据存放在缓冲区
void TLV::send_data(const char* msg,int len){
    if(len<0){
        printf("长度为复数\n");
        return;
    }else if(len>DATA_MAX_SIZE){
        printf("长度超出缓冲区大小\n");
        return;
    }else if(msg!=nullptr){
        memcpy(data,msg,len);
    }
}
//获取数据的类型
int TLV::get_type(){
    return ntohl(_type);
}
//获取数据的以字节表示的长度
int TLV::get_length(){
    return ntohl(_length);
}
//获取value实际数据的首地址
const char* TLV::get_data(){
    return data;
}
//获取TLV对象结构的首地址
//返回 const void*，是为了适配网络发送函数（如 send）的参数要求 ——send 函数的第二个参数类型就是 const void*，
//用于接收 “任意类型的二进制数据地址”
const void* TLV::get_tlv_buff(){
    return this;
}

//获取整个TLV数据的总字节大小
int TLV::get_total_size(){
    return 4+4+get_length();
}
//打印调试
void TLV::print(){
    cout<<"=================TLV结构体信息================"<<endl;
    cout<<"Type："<<get_type()<<"(0x"<<std::hex<<std::setw(2)<<std::setfill('0')
        <<get_type()<<")"<<std::dec<<endl;
    cout<<"Length:"<<get_length()<<" 字节"<<endl;
    // 打印数据的十六进制形式
    std::cout << "Data (十六进制): ";
    for (int i = 0; i < get_length(); ++i) {
        // 将char转换为unsigned int并取低8位，避免符号位影响
        std::cout << std::hex << std::setw(2) << std::setfill('0') 
            << (static_cast<unsigned int>(data[i]) & 0xFF) << " ";
    }
    std::cout << std::dec << std::endl;  // 恢复十进制输出
                                         // 打印数据的字符串形式（仅可打印字符）
    std::cout << "Data (字符串): ";
    for (int i = 0; i < get_length(); ++i) {
        if (isprint(static_cast<unsigned char>(data[i]))) {
            std::cout << data[i];
        } else {
            std::cout << ".";  // 不可打印字符用'.'表示
        }
    }
    std::cout << std::endl << "========================" << std::endl;
}
std::unique_ptr<TLV> TLV::parse_tlv_buff(const char* recvbuf,int recv_len){
    if(recvbuf ==nullptr || recv_len<0){
        cout<<"解析失败"<<endl;
        return nullptr;
    } 
    int tlvType_net,tlvLength_net;
    //获取类型和数据的长度
    memcpy(&tlvType_net,recvbuf,4);
    memcpy(&tlvLength_net,recvbuf+4,4);
    //转换为主机字节序
    int tlvType_host=ntohl(tlvType_net);
    int tlvLength_host=ntohl(tlvLength_net);

    int alldata_length=4+4+tlvLength_host;
    if(alldata_length!=recv_len){
        cout<<"数据解析不完整，实际接收:"<<recv_len<<" 字节"<<endl;
        return nullptr;       
    }

    const char* tlv_data=recvbuf+8;
    return std::unique_ptr<TLV>(new TLV(tlvType_host,tlvLength_host,tlv_data));

}
}//end of namespace wd
